#!/usr/bin/python
# -*- coding: utf-8 -*-

from copy import copy

class Player:

	def __init__(self):
		#variable I need to keep track between round, or between the function call in one round
		self.h=0
		self.s=0
		self.h_this_round=0


	def clustering2(self,player_reputations):
		"""
		This function apply a simple K-mean clustering to the player's reputation in order to divide them into two group.
		The two calculated means are returned.
		"""
		reputations=copy(player_reputations)#make a copy of the reputation to manipulate
		reputations.sort()
		
		
		#treat exeption that will make the algorythne fail.
	
		if len(reputations)==0:
		#should not occur, but to be consistent, return valids data...
			return [1,1]
		if len(reputations)==1:
			#if I play only against one player, I'll try to imitate him, so my goal should be his reputation
			return [reputations[0],reputations[0]]
		if reputations[0]==reputations[-1]:
			#if all the player have the same reputation, my goal is this reputation
			return [reputations[0],reputations[0]]
		
		
		
		
		mu=[-0.1,1.1]#dummy initialisation that garantie the good execution of the first loop
		new_mu=[reputations[0],reputations[-1]]#initialised centroids with the two extreme.
		
		while mu!=new_mu:
			mu=new_mu
			index=list()
			for reputation in reputations:
				dist=[abs(reputation-mu[0]),abs(reputation-mu[1])]
				if dist[0]<dist[1]: 
					#closer to mu[0]. so index assigned =0
					index.append(0)
				else:
					#closer to mu[1]
					index.append(1)
			
			#compute new mu
			total=[0,0]
			player_in_groups=[0,0]#number of players in each set
			for i in range(len(reputations)):
				total[index[i]]+=reputations[i]
				player_in_groups[index[i]]+=1
			new_mu=[float(total[0])/player_in_groups[0],float(total[1])/player_in_groups[1]]	
			
		return new_mu
	
	def hunt_choices(self,round_number, current_food, current_reputation, m,  player_reputations):
		player_number=len(player_reputations)
		hunt_decisions=list()	
		
		#I need an sorted list of the reputation to work with
		reputations=copy(player_reputations)
		reputations.sort()
		
		
		if round_number==1:
			#for the first round, I cannot rely to the reputation of the player to get a mean as a goal.
			#So I just define it myself.
			desire_reputation=1.
			
		else: #common case
			#I divise people into 2 set, based on their réputation, with a simple K-mean clustering.
			#the best reputation's set is considered as the trustworthy set.
			#my goal is to always be in this set. So I'll always define my reputation goal to the mean of this set.
			means=self.clustering2(player_reputations)
			desire_reputation=means[1]
			
		
		#now that I know my desire_reputation at the end of this round, I compute the number of hunt I should go
		hunt_to_go_this_round=desire_reputation*(self.h+self.s+player_number)-self.h
		
		#round to the nearer int
		self.h_this_round=int(round(hunt_to_go_this_round))
		
		#if desire_reputation is very low the above formula will lead to a negative number of hunt I should go.
		#if it is high, it may lead to a number greater than the number of player
		#I rectify that to the possibility 
		if self.h_this_round<0:
			self.h_this_round=0
		if self.h_this_round>player_number:
			self.h_this_round=player_number
		
		
		#I will spend my hunts, with the player with the biggest reputation. So I need to find them.
		#save the hunt_to_go_this_round best reputation, that's the player I will hunt with
		if self.h_this_round==0:
			hunt_with=list()
		else:
			hunt_with=reputations[-self.h_this_round:]
		
		#finally, create the answer vector, in the same order as the reputation are given
		for reputation in player_reputations:
			if reputation in hunt_with:
				hunt_decisions.append('h')
				self.h+=1
				
				#remove one occurence, in the case two players have the same reputation and I should hunt only with one of them
				#(mostly useful if a BUNCH of people have say 0 or 1 as reputation..)
				hunt_with.remove(reputation)
			else:
				hunt_decisions.append('s')
				self.s+=1
		
		return hunt_decisions

	def hunt_outcomes(self,food_earnings):
		#I do not take this into account
		pass 

	def round_end(self,award, m, number_hunters):
		#number_hunters could possibly used to determine the two groups hunters/slackers more efficiently/reliably...
		#But as only a one time information it can have an observations bias.
		#I will not used this information because as the hunters may slack from times to times, I will get horrible result if a lot of them, by coincidence, slacks in the same round.
		pass
